package main.model.critters.genetics;

import java.util.ArrayList;
import java.util.Random;


/**
 * Based on Totro.pl (Version 1.20, 2006-04-19)
 * Original copyright (C) 2002-2006 David A. Wheeler and Chris X. Edwards.
 * Original source can be found at http://www.dwheeler.com/totro.pl.txt
 * 
 * This version was translated into java by Gabe.
 * 
 * List of possible vowels, followed by list of possible consonants.
 * In both lists, duplicates increase the likelihood of that selection.
 * The second parameter indicates if the syllable can occur
 * at the beginning, middle, or ending of a name, as follows:
 *	  MBE
 *	1 001	ending
 *	2 010	beginning
 *	3 011	beginning or ending
 *	4 100	middle
 *	5 101	middle or ending	
 *	6 110	beginning or middle
 *	7 111	anywhere
 * 
 * @author gabe
 *
 */
public class NameFactory {

	static ArrayList<Sylab> vowels = new ArrayList<Sylab>();
	static ArrayList<Sylab> consonants = new ArrayList<Sylab>();
	
	static int[] B = {2,3,6,7};//Beginning
	static int[] M = {4,5,6,7};//Middle
	static int[] E = {1,3,5,7};//End
	
	public NameFactory(){
		buildVowels();
		buildConsonants();
	}
	
	private int chooseLeng(int minvalue, int maxvalue) {
		Random random = new Random();
	    int diff = maxvalue - minvalue;
	    //force correct relative sizes
	    if (diff < 0){
	    	return random.nextInt(diff)+minvalue;
	    }else if(diff > 0){
	    	return random.nextInt(diff)+minvalue;
	    }else{
	    	return maxvalue;
	    }
	}
	
	public String newName(){
		int MINSYL = 3;
		int MAXSYL= 6;
		return newName(MINSYL, MAXSYL);
	}
	
	public String newName(int minsyl, int maxsyl){
		//Create a random name.  It must have at least between minsyl and maxsyl
		//number of syllables (inclusive).
		
		String genName = "";	// this accumulates the generated name.
		int leng = chooseLeng(minsyl, maxsyl); //Compute number of syllables in the name
		
		Random random = new Random();
		int isVowel = random.nextInt(2); //randomly start with vowel or consonant
		for (int i = 1; i<leng; i++){ //# syllable #. Start is 1 (not 0)
			Sylab sy;
			//Pick a potential syllable until we find a good one.
			while(true){
				if (isVowel % 2 == 0) {
					sy = vowels.get(random.nextInt(vowels.size()));
				} else {
					sy = consonants.get(random.nextInt(consonants.size()));
				}
				
				//Check if this syllable can occur in this part of the name.
				if (i == 1) { //first syllable.
					if (find(B, sy.getLoci())) {break;}
				} else if (i == leng-1) { //last syllable.
					if (find(E, sy.getLoci())) {break;}
				} else { //Middle syllable
					if (find(M, sy.getLoci())) {break;}
				}
			//If got here, it wasn't an okay pick. Try again.
			}
			genName = genName + sy.getSyl();  //Found good one, add to name.
			isVowel = isVowel + 1; //Alternate between vowels and consonants.
		}
		genName = Character.toUpperCase(genName.charAt(0)) + genName.substring(1);
		return genName;
	}
		
	private boolean find(int[] a, int q){
		for(int i = 0; i<a.length; i++){
			if(a[i] == q){
				return true;
			}
		}
		return false;
	}
	
	private void buildVowels(){
		for(int i = 0; i<12; i++){
			vowels.add(new Sylab("a",7));	vowels.add(new Sylab("e",7));
			vowels.add(new Sylab("i",7));	vowels.add(new Sylab("o",7));
			vowels.add(new Sylab("u",7));
		}
		vowels.add(new Sylab("ea",7));	vowels.add(new Sylab("eo",7));
		vowels.add(new Sylab("eu",7));	vowels.add(new Sylab("ee",7));
		vowels.add(new Sylab("eau",7));

		vowels.add(new Sylab("ia",7));	vowels.add(new Sylab("io",7));
		vowels.add(new Sylab("iu",7));	vowels.add(new Sylab("ii",7));
		
		vowels.add(new Sylab("oa",7));	vowels.add(new Sylab("oe",7));
		vowels.add(new Sylab("oi",7));	vowels.add(new Sylab("ou",7));
		vowels.add(new Sylab("oo",7));

		vowels.add(new Sylab("'",4));	vowels.add(new Sylab("y",7));
		
		vowels.add(new Sylab("ay",7));	vowels.add(new Sylab("ay",7));
		
		vowels.add(new Sylab("ei",7));	vowels.add(new Sylab("ei",7));
		vowels.add(new Sylab("ei",7));
		
		vowels.add(new Sylab("ua",7));	vowels.add(new Sylab("ua",7));	
	}
	
	private void buildConsonants(){
		for(int i = 0; i<3; i++){
			consonants.add(new Sylab("b", 7));	consonants.add(new Sylab("c", 7));
			consonants.add(new Sylab("d", 7));	consonants.add(new Sylab("f", 7));
			consonants.add(new Sylab("g", 7));	consonants.add(new Sylab("h", 7));
		 
			consonants.add(new Sylab("j", 7));	consonants.add(new Sylab("k", 7));
			consonants.add(new Sylab("l", 7));	consonants.add(new Sylab("m", 7));
			consonants.add(new Sylab("n", 7));	consonants.add(new Sylab("p", 7));
		 
			consonants.add(new Sylab("qu", 6));	consonants.add(new Sylab("r", 7));
			consonants.add(new Sylab("s", 7));	consonants.add(new Sylab("t", 7));
			consonants.add(new Sylab("v", 7));	consonants.add(new Sylab("w", 7));

			consonants.add(new Sylab("x", 7));	consonants.add(new Sylab("y", 7));
			consonants.add(new Sylab("z", 7));
		}
		//Blends, sorted by second character:
		consonants.add(new Sylab("sc", 7));	consonants.add(new Sylab("ch", 7));
		consonants.add(new Sylab("gh", 7));	consonants.add(new Sylab("ph", 7));
		consonants.add(new Sylab("sh", 7));	consonants.add(new Sylab("th", 7));
		consonants.add(new Sylab("wh", 6));	consonants.add(new Sylab("ck", 5));
		consonants.add(new Sylab("nk", 5));	consonants.add(new Sylab("rk", 5));
		consonants.add(new Sylab("sk", 7));	consonants.add(new Sylab("wk", 0));
		consonants.add(new Sylab("cl", 6));	consonants.add(new Sylab("fl", 6));
		consonants.add(new Sylab("gl", 6));	consonants.add(new Sylab("kl", 6));
		consonants.add(new Sylab("ll", 6));	consonants.add(new Sylab("pl", 6));
		consonants.add(new Sylab("sl", 6));	consonants.add(new Sylab("br", 6));
		consonants.add(new Sylab("cr", 6));	consonants.add(new Sylab("dr", 6));
		consonants.add(new Sylab("fr", 6));	consonants.add(new Sylab("gr", 6));
		consonants.add(new Sylab("kr", 6));	consonants.add(new Sylab("pr", 6));
		consonants.add(new Sylab("sr", 6));	consonants.add(new Sylab("tr", 6));
		consonants.add(new Sylab("ss", 5));	consonants.add(new Sylab("st", 7));
		consonants.add(new Sylab("str", 6));

		//Repeat some entries to make them more common.
		consonants.add(new Sylab("br", 6));	consonants.add(new Sylab("dr", 6));
		consonants.add(new Sylab("fr", 6));	consonants.add(new Sylab("gr", 6));
		consonants.add(new Sylab("kr", 6));

		consonants.add(new Sylab("xx", 7));	consonants.add(new Sylab("xx",5));
	}
	
	public class Sylab{
		String syl;
		int loci;
		public Sylab(String syl, int loci){
			this.syl=syl;
			this.loci=loci; 
		}
		public String getSyl(){return syl;}
		public int getLoci(){return loci;}
	}

}
